--! This file is part of the Wupper firmware distribution (https://gitlab.nikhef.nl/franss/wupper).
--! Copyright (C) 2001-2021 CERN for the benefit of the ATLAS collaboration.
--! Authors:
--!               Frans Schreuder
--!
--!   Licensed under the Apache License, Version 2.0 (the "License");
--!   you may not use this file except in compliance with the License.
--!   You may obtain a copy of the License at
--!
--!       http://www.apache.org/licenses/LICENSE-2.0
--!
--!   Unless required by applicable law or agreed to in writing, software
--!   distributed under the License is distributed on an "AS IS" BASIS,
--!   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
--!   See the License for the specific language governing permissions and
--!   limitations under the License.





library ieee, UNISIM, XPM;
    use ieee.numeric_std.all;
    use UNISIM.VCOMPONENTS.all;
    use XPM.VCOMPONENTS.all;
    use ieee.numeric_std_unsigned.all;
    use ieee.std_logic_1164.all;
    use work.pcie_package.all;

entity WupperFifos is
    generic(
        NUMBER_OF_DESCRIPTORS : integer := 3;
        DATA_WIDTH            : integer := 256;
        USE_ULTRARAM          : boolean ;
        FIRMWARE_MODE         : integer);
    port (
        fromHostFifo_din                     : in     std_logic_vector(DATA_WIDTH-1 downto 0);
        fromHostFifo_dout                    : out    std_logic_vector(DATA_WIDTH-1 downto 0);
        fromHostFifo_empty                   : out    std_logic;
        fromHostFifo_full                    : out    std_logic;
        fromHostFifo_pfull_threshold_assert  : in     std_logic_vector(8 downto 0);
        fromHostFifo_pfull_threshold_negate  : in     std_logic_vector(8 downto 0);
        fromHostFifo_prog_full               : out    std_logic;
        fromHostFifo_rd_clk                  : in     std_logic;
        fromHostFifo_rd_en                   : in     std_logic;
        fromHostFifo_rst                     : in     std_logic;
        fromHostFifo_we                      : in     std_logic;
        fromHostFifo_wr_clk                  : in     std_logic;
        toHostFifoIndex                      : in     integer range 0 to NUMBER_OF_DESCRIPTORS-2;
        toHostFifo_din                       : in     slv_array(0 to NUMBER_OF_DESCRIPTORS-2);
        toHostFifo_dout                      : out    std_logic_vector(DATA_WIDTH-1 downto 0);
        toHostFifo_empty_thresh              : in     slv12_array(0 to NUMBER_OF_DESCRIPTORS-2);
        toHostFifo_pfull_threshold_assert    : in     std_logic_vector(11 downto 0);
        toHostFifo_pfull_threshold_negate    : in     std_logic_vector(11 downto 0);
        toHostFifo_prog_empty                : out    std_logic_vector(NUMBER_OF_DESCRIPTORS-2 downto 0);
        toHostFifo_empty                     : out    std_logic_vector(NUMBER_OF_DESCRIPTORS-2 downto 0);
        toHostFifo_prog_full                 : out    std_logic_vector(NUMBER_OF_DESCRIPTORS-2 downto 0);
        toHostFifo_rd_clk                    : in     std_logic;
        toHostFifo_re                        : in     std_logic;
        toHostFifo_rst                       : in     std_logic;
        toHostFifo_wr_clk                    : in     std_logic;
        toHostFifo_wr_en                     : in     std_logic_vector(NUMBER_OF_DESCRIPTORS-2 downto 0)
    );
end entity WupperFifos;



architecture rtl of WupperFifos is

    signal toHostFifo_dout_array        : slv_array(0 to NUMBER_OF_DESCRIPTORS-2);
    signal toHostFifo_re_array          : std_logic_vector(NUMBER_OF_DESCRIPTORS-2 downto 0);
    constant FROMHOSTFIFO_DEPTH : integer := 512;
    signal fromHostFifo_wr_data_count : std_logic_vector(f_log2(FROMHOSTFIFO_DEPTH) downto 0);
    signal fromHostFifo_we_i: std_logic;
    signal fromHostFifo_rd_en_i: std_logic;
    signal toHostFifo_pfull_threshold_assert_s : std_logic_vector(12 downto 0);
    signal toHostFifo_pfull_threshold_negate_s : std_logic_vector(12 downto 0);
    --type slv13_array is array(natural range <>) of std_logic_vector(12 downto 0);
    --signal toHostFifo_wr_data_count_array_s : slv13_array(0 to NUMBER_OF_DESCRIPTORS-2);
    signal fromHostFifo_rst_sync: std_logic;
begin
    toHostFifo_pfull_threshold_assert_s(11 downto 0) <= toHostFifo_pfull_threshold_assert(11 downto 0);
    toHostFifo_pfull_threshold_negate_s(11 downto 0) <= toHostFifo_pfull_threshold_negate(11 downto 0);

    fromHostFifo_we_i <= fromHostFifo_we;
    fromHostFifo_rd_en_i <= fromHostFifo_rd_en;
    g_bram0: if USE_ULTRARAM = false generate
        xpm_cdc_sync_fromHostFifo_rst_inst : xpm_cdc_sync_rst
            generic map (
                DEST_SYNC_FF => 2,
                INIT => 1,
                INIT_SYNC_FF => 0,
                SIM_ASSERT_CHK => 0
            )
            port map (
                src_rst => fromHostFifo_rst,
                dest_clk => fromHostFifo_wr_clk,
                dest_rst => fromHostFifo_rst_sync
            );


        fromHostFifo0 : xpm_fifo_async
            generic map ( -- @suppress "Generic map uses default values. Missing optional actuals: CASCADE_HEIGHT, SIM_ASSERT_CHK"
                FIFO_MEMORY_TYPE => "block", --string; "auto", "block", or "distributed";
                FIFO_WRITE_DEPTH => FROMHOSTFIFO_DEPTH, --positive integer
                RELATED_CLOCKS => 0, --positive integer; 0 or 1
                WRITE_DATA_WIDTH => DATA_WIDTH, --positive integer
                READ_MODE => "std", --string; "std" or "fwft";
                FIFO_READ_LATENCY => 1, --positive integer
                FULL_RESET_VALUE => 0, --positive integer; 0 or 1;
                USE_ADV_FEATURES => "0004", -- String
                READ_DATA_WIDTH => DATA_WIDTH, --positive integer
                CDC_SYNC_STAGES => 2, --positive integer
                WR_DATA_COUNT_WIDTH => f_log2(FROMHOSTFIFO_DEPTH)+1, --positive integer
                PROG_FULL_THRESH => FROMHOSTFIFO_DEPTH-10, --positive integer
                RD_DATA_COUNT_WIDTH => f_log2(FROMHOSTFIFO_DEPTH)+1, --positive integer
                PROG_EMPTY_THRESH => 10, --positive integer
                DOUT_RESET_VALUE => "0", --string
                ECC_MODE => "no_ecc", --string; "no_ecc" or "en_ecc";
                WAKEUP_TIME => 2 --positive integer; 0 or 2;
            )
            port map (
                sleep => '0',
                rst => fromHostFifo_rst_sync,
                wr_clk => fromHostFifo_wr_clk,
                wr_en => fromHostFifo_we_i,
                din => fromHostFifo_din,
                full => fromHostFifo_full,
                prog_full => open,
                wr_data_count => fromHostFifo_wr_data_count,
                overflow => open,
                wr_rst_busy => open,
                almost_full => open,
                wr_ack => open,
                rd_clk => fromHostFifo_rd_clk,
                rd_en => fromHostFifo_rd_en_i,
                dout => fromHostFifo_dout,
                empty => fromHostFifo_empty,
                prog_empty => open,
                rd_data_count => open,
                underflow => open,
                rd_rst_busy => open,
                almost_empty => open,
                data_valid => open,
                injectsbiterr => '0',
                injectdbiterr => '0',
                sbiterr => open,
                dbiterr => open
            );
    end generate;
    g_uram0: if USE_ULTRARAM generate
        signal fromHostFifo_wr_data_count_rd_clk : std_logic_vector(f_log2(FROMHOSTFIFO_DEPTH)-1 downto 0);
        signal fromHostFifo_rst_rd_clk: std_logic;
        signal fromHostFifo_rst_wr_clk: std_logic;
        signal fromHostFifo_distr0_rd_en: std_logic;
        signal fromHostFifo_distr0_dout: std_logic_vector(DATA_WIDTH-1 downto 0);
        signal fromHostFifo_distr0_empty: std_logic;
        signal fromHostFifo_distr0_dvalid: std_logic;
        signal fromHostFifo_uram0_wr_en: std_logic;
        signal fromHostFifo_uram0_din: std_logic_vector(DATA_WIDTH-1 downto 0);
        signal fromHostFifo_uram0_full: std_logic;
    begin

        xpm_cdc_gray_wr_data_count : xpm_cdc_gray
            generic map (
                DEST_SYNC_FF => 2,
                INIT_SYNC_FF => 0,
                REG_OUTPUT => 0,
                SIM_ASSERT_CHK => 0,
                SIM_LOSSLESS_GRAY_CHK => 0,
                WIDTH => f_log2(FROMHOSTFIFO_DEPTH)
            )
            port map (
                src_clk => fromHostFifo_rd_clk,
                src_in_bin => fromHostFifo_wr_data_count_rd_clk,
                dest_clk => fromHostFifo_wr_clk,
                dest_out_bin => fromHostFifo_wr_data_count(f_log2(FROMHOSTFIFO_DEPTH)-1 downto 0)
            );

        xpm_cdc_sync_rst_fromHostFifoRd_clk: xpm_cdc_sync_rst
            generic map (
                DEST_SYNC_FF => 2,
                INIT => 1,
                INIT_SYNC_FF => 0,
                SIM_ASSERT_CHK => 0
            )
            port map (
                src_rst => fromHostFifo_rst,
                dest_clk => fromHostFifo_rd_clk,
                dest_rst => fromHostFifo_rst_rd_clk
            );

        xpm_cdc_sync_rst_fromHostFifowr_clk: xpm_cdc_sync_rst
            generic map (
                DEST_SYNC_FF => 2,
                INIT => 1,
                INIT_SYNC_FF => 0,
                SIM_ASSERT_CHK => 0
            )
            port map (
                src_rst => fromHostFifo_rst,
                dest_clk => fromHostFifo_wr_clk,
                dest_rst => fromHostFifo_rst_wr_clk
            );

        fromHostFifo_distr0 : xpm_fifo_async
            generic map ( -- @suppress "Generic map uses default values. Missing optional actuals: CASCADE_HEIGHT, SIM_ASSERT_CHK"
                FIFO_MEMORY_TYPE => "distributed", --string; "auto", "block", or "distributed";
                FIFO_WRITE_DEPTH => 16, --positive integer
                RELATED_CLOCKS => 0, --positive integer; 0 or 1
                WRITE_DATA_WIDTH => DATA_WIDTH, --positive integer
                READ_MODE => "std", --string; "std" or "fwft";
                FIFO_READ_LATENCY => 1, --positive integer
                FULL_RESET_VALUE => 0, --positive integer; 0 or 1;
                USE_ADV_FEATURES => "0004", -- String
                READ_DATA_WIDTH => DATA_WIDTH, --positive integer
                CDC_SYNC_STAGES => 2, --positive integer
                WR_DATA_COUNT_WIDTH => 4, --positive integer
                PROG_FULL_THRESH => 10, --positive integer
                RD_DATA_COUNT_WIDTH => 4, --positive integer
                PROG_EMPTY_THRESH => 5, --positive integer
                DOUT_RESET_VALUE => "0", --string
                ECC_MODE => "no_ecc", --string; "no_ecc" or "en_ecc";
                WAKEUP_TIME => 0 --positive integer; 0 or 2;
            )
            port map (
                sleep => '0',
                rst => fromHostFifo_rst_wr_clk,
                wr_clk => fromHostFifo_wr_clk,
                wr_en => fromHostFifo_we_i,
                din => fromHostFifo_din,
                full => fromHostFifo_full,
                prog_full => open,
                wr_data_count => open,
                overflow => open,
                wr_rst_busy => open,
                almost_full => open,
                wr_ack => open,
                rd_clk => fromHostFifo_rd_clk,
                rd_en => fromHostFifo_distr0_rd_en,
                dout => fromHostFifo_distr0_dout,
                empty => fromHostFifo_distr0_empty,
                prog_empty => open,
                rd_data_count => open,
                underflow => open,
                rd_rst_busy => open,
                almost_empty => open,
                data_valid => open,
                injectsbiterr => '0',
                injectdbiterr => '0',
                sbiterr => open,
                dbiterr => open
            );

        fromHostFifo_distr0_rd_en <= not fromHostFifo_distr0_empty and not fromHostFifo_uram0_full;
        fromHostFifo_uram0_din<= fromHostFifo_distr0_dout;
        fromHostFifo_uram0_wr_en <= fromHostFifo_distr0_dvalid;

        process(fromHostFifo_rd_clk)
        begin
            if rising_edge(fromHostFifo_rd_clk) then
                fromHostFifo_distr0_dvalid <= fromHostFifo_distr0_rd_en;
            end if;
        end process;

        fromHostFifo_uram0 : xpm_fifo_sync
            generic map ( -- @suppress "Generic map uses default values. Missing optional actuals: CASCADE_HEIGHT, SIM_ASSERT_CHK"
                FIFO_MEMORY_TYPE => "ultra", --string; "auto", "block", or "distributed";
                FIFO_WRITE_DEPTH => FROMHOSTFIFO_DEPTH, --positive integer
                WRITE_DATA_WIDTH => DATA_WIDTH, --positive integer
                READ_MODE => "std", --string; "std" or "fwft";
                FIFO_READ_LATENCY => 1, --positive integer
                FULL_RESET_VALUE => 1, --positive integer; 0 or 1;
                USE_ADV_FEATURES => "0004", -- String
                READ_DATA_WIDTH => DATA_WIDTH, --positive integer
                WR_DATA_COUNT_WIDTH => f_log2(FROMHOSTFIFO_DEPTH), --positive integer
                PROG_FULL_THRESH => FROMHOSTFIFO_DEPTH-10, --positive integer
                RD_DATA_COUNT_WIDTH => f_log2(FROMHOSTFIFO_DEPTH), --positive integer
                PROG_EMPTY_THRESH => 10, --positive integer
                DOUT_RESET_VALUE => "0", --string
                ECC_MODE => "no_ecc", --string; "no_ecc" or "en_ecc";
                WAKEUP_TIME => 2 --positive integer; 0 or 2;
            )
            port map (
                sleep => '0',
                rst => fromHostFifo_rst_rd_clk,
                wr_clk => fromHostFifo_rd_clk,
                wr_en => fromHostFifo_uram0_wr_en,
                din => fromHostFifo_uram0_din,
                full => fromHostFifo_uram0_full,
                prog_full => open,
                wr_data_count => fromHostFifo_wr_data_count_rd_clk,
                overflow => open,
                wr_rst_busy => open,
                almost_full => open,
                wr_ack => open,
                rd_en => fromHostFifo_rd_en_i,
                dout => fromHostFifo_dout,
                empty => fromHostFifo_empty,
                prog_empty => open,
                rd_data_count => open,
                underflow => open,
                rd_rst_busy => open,
                almost_empty => open,
                data_valid => open,
                injectsbiterr => '0',
                injectdbiterr => '0',
                sbiterr => open,
                dbiterr => open
            );
    end generate;

    fromhost_prog_full_proc: process(fromHostFifo_wr_clk)
    begin
        if rising_edge(fromHostFifo_wr_clk) then
            if fromHostFifo_wr_data_count(f_log2(FROMHOSTFIFO_DEPTH)-1 downto 0) >= fromHostFifo_pfull_threshold_assert then
                fromHostFifo_prog_full <= '1';
            elsif fromHostFifo_wr_data_count(f_log2(FROMHOSTFIFO_DEPTH)-1 downto 0) <= fromHostFifo_pfull_threshold_negate then
                fromHostFifo_prog_full <= '0';
            end if;
        end if;
    end process;



    mux1: process (toHostFifoIndex, toHostFifo_re,
    toHostFifo_dout_array)
    begin
        toHostFifo_dout                         <= toHostFifo_dout_array(toHostFifoIndex)(DATA_WIDTH-1 downto 0); -- @suppress "Incorrect array size in assignment: expected (<DATA_WIDTH>) but was (<256>)"
        toHostFifo_re_array <= (others => '0');
        toHostFifo_re_array(toHostFifoIndex)    <= toHostFifo_re;
    end process mux1 ;

    g_tohost: for i in 0 to NUMBER_OF_DESCRIPTORS-2 generate
        signal toHostFifo_wr_en_pipe : std_logic;
        signal toHostFifo_din_pipe   : std_logic_vector(DATA_WIDTH-1 downto 0);
        signal toHostFifo_wr_data_count_s : std_logic_vector(f_log2(TOHOSTFIFO_DEPTH(NUMBER_OF_DESCRIPTORS,FIRMWARE_MODE)) downto 0);
        signal toHostFifo_rd_data_count_s : std_logic_vector(f_log2(TOHOSTFIFO_DEPTH(NUMBER_OF_DESCRIPTORS,FIRMWARE_MODE)) downto 0);
        signal toHostFifo_prog_full_s: std_logic;
        signal toHostFifo_prog_empty_s: std_logic;
        signal wr_rst_busy : std_logic;
        signal wr_rst_busy_wr_clk : std_logic;
    begin



        g_BRAM: if USE_ULTRARAM = false generate
            signal toHostFifo_rst_wr_clk: std_logic;
        begin
            xpm_cdc_sync_rst_toHostFifo_rst_250: xpm_cdc_sync_rst
                generic map (
                    DEST_SYNC_FF => 2,
                    INIT => 1,
                    INIT_SYNC_FF => 0,
                    SIM_ASSERT_CHK => 0
                )
                port map (
                    src_rst => toHostFifo_rst,
                    dest_clk => toHostFifo_wr_clk,
                    dest_rst => toHostFifo_rst_wr_clk
                );
            toHostFifo0 : xpm_fifo_async
                generic map (  -- @suppress "Generic map uses default values. Missing optional actuals: CASCADE_HEIGHT, SIM_ASSERT_CHK"
                    FIFO_MEMORY_TYPE => "block", --string; "auto", "block", or "distributed";
                    FIFO_WRITE_DEPTH => TOHOSTFIFO_DEPTH(NUMBER_OF_DESCRIPTORS,FIRMWARE_MODE), --positive integer
                    RELATED_CLOCKS => 0, --positive integer; 0 or 1
                    WRITE_DATA_WIDTH => DATA_WIDTH, --positive integer
                    READ_MODE => "fwft", --string; "std" or "fwft";
                    FIFO_READ_LATENCY => 1, --positive integer
                    FULL_RESET_VALUE => 1, --positive integer; 0 or 1;
                    USE_ADV_FEATURES => "0404", -- String
                    READ_DATA_WIDTH => DATA_WIDTH, --positive integer
                    CDC_SYNC_STAGES => 2, --positive integer
                    WR_DATA_COUNT_WIDTH => f_log2(TOHOSTFIFO_DEPTH(NUMBER_OF_DESCRIPTORS,FIRMWARE_MODE))+1, --positive integer
                    PROG_FULL_THRESH => TOHOSTFIFO_DEPTH(NUMBER_OF_DESCRIPTORS,FIRMWARE_MODE)-10, --positive integer
                    RD_DATA_COUNT_WIDTH => f_log2(TOHOSTFIFO_DEPTH(NUMBER_OF_DESCRIPTORS,FIRMWARE_MODE))+1, --positive integer
                    PROG_EMPTY_THRESH => 10, --positive integer
                    DOUT_RESET_VALUE => "0", --string
                    ECC_MODE => "no_ecc", --string; "no_ecc" or "en_ecc";
                    WAKEUP_TIME => 2 --positive integer; 0 or 2;
                )
                port map (
                    sleep => '0',
                    rst => toHostFifo_rst_wr_clk,
                    wr_clk => toHostFifo_wr_clk,
                    wr_en => toHostFifo_wr_en_pipe,
                    din => toHostFifo_din_pipe,
                    full => open,
                    prog_full => open,
                    wr_data_count => toHostFifo_wr_data_count_s,
                    overflow => open,
                    wr_rst_busy => wr_rst_busy,
                    almost_full => open,
                    wr_ack => open,
                    rd_clk => toHostFifo_rd_clk,
                    rd_en => toHostFifo_re_array(i),
                    dout => toHostFifo_dout_array(i)(DATA_WIDTH-1 downto 0),
                    empty => toHostFifo_empty(i),
                    prog_empty => open,
                    rd_data_count => toHostFifo_rd_data_count_s,
                    underflow => open,
                    rd_rst_busy => open,
                    almost_empty => open,
                    data_valid => open,
                    injectsbiterr => '0',
                    injectdbiterr => '0',
                    sbiterr => open,
                    dbiterr => open
                );
        end generate;
        g_URAM: if USE_ULTRARAM generate
            signal toHostFifo_rst_250, toHostFifo_rst_wr_clk: std_logic;
            signal toHostFifoUram_wr_en   : std_logic;
            signal toHostFifoUram_din     : std_logic_vector(DATA_WIDTH-1 downto 0);
            signal toHostFifoUram_full    : std_logic;
            signal toHostFifoDistr_dout   : std_logic_vector(DATA_WIDTH-1 downto 0);
            signal toHostFifoDistr_empty  : std_logic;
            signal toHostFifoDistr_rd_en  : std_logic;
            signal toHostFifoDistr_dvalid : std_logic;
            signal toHostFifo_wr_data_count_s_rd_clk : std_logic_vector(f_log2(TOHOSTFIFO_DEPTH(NUMBER_OF_DESCRIPTORS,FIRMWARE_MODE)) downto 0);
        begin

            xpm_cdc_gray_wr_data_count : xpm_cdc_gray
                generic map (
                    DEST_SYNC_FF => 2,
                    INIT_SYNC_FF => 0,
                    REG_OUTPUT => 0,
                    SIM_ASSERT_CHK => 0,
                    SIM_LOSSLESS_GRAY_CHK => 0,
                    WIDTH => f_log2(TOHOSTFIFO_DEPTH(NUMBER_OF_DESCRIPTORS,FIRMWARE_MODE))+1
                )
                port map (
                    src_clk => toHostFifo_rd_clk,
                    src_in_bin => toHostFifo_wr_data_count_s_rd_clk,
                    dest_clk => toHostFifo_wr_clk,
                    dest_out_bin => toHostFifo_wr_data_count_s
                );

            xpm_cdc_sync_rst_toHostFifo_rst_250: xpm_cdc_sync_rst
                generic map (
                    DEST_SYNC_FF => 2,
                    INIT => 1,
                    INIT_SYNC_FF => 0,
                    SIM_ASSERT_CHK => 0
                )
                port map (
                    src_rst => toHostFifo_rst,
                    dest_clk => toHostFifo_rd_clk,
                    dest_rst => toHostFifo_rst_250
                );

            xpm_cdc_sync_rst_toHostFifo_rst_wr_clk: xpm_cdc_sync_rst
                generic map (
                    DEST_SYNC_FF => 2,
                    INIT => 1,
                    INIT_SYNC_FF => 0,
                    SIM_ASSERT_CHK => 0
                )
                port map (
                    src_rst => toHostFifo_rst,
                    dest_clk => toHostFifo_wr_clk,
                    dest_rst => toHostFifo_rst_wr_clk
                );
            --Ultraram can't be asynchronous, so we place a small distributed ram fifo in front for clock domain crossing
            toHostFifoDistr0 : xpm_fifo_async
                generic map (  -- @suppress "Generic map uses default values. Missing optional actuals: CASCADE_HEIGHT, SIM_ASSERT_CHK"
                    FIFO_MEMORY_TYPE => "distributed", --string; "auto", "block", or "distributed";
                    FIFO_WRITE_DEPTH => 16, --positive integer
                    RELATED_CLOCKS => 0, --positive integer; 0 or 1
                    WRITE_DATA_WIDTH => DATA_WIDTH, --positive integer
                    READ_MODE => "std", --string; "std" or "fwft";
                    FIFO_READ_LATENCY => 1, --positive integer
                    FULL_RESET_VALUE => 1, --positive integer; 0 or 1;
                    USE_ADV_FEATURES => "0404", -- String
                    READ_DATA_WIDTH => DATA_WIDTH, --positive integer
                    CDC_SYNC_STAGES => 2, --positive integer
                    WR_DATA_COUNT_WIDTH => 4,
                    PROG_FULL_THRESH => 10, --positive integer
                    RD_DATA_COUNT_WIDTH => 4,
                    PROG_EMPTY_THRESH => 5, --positive integer
                    DOUT_RESET_VALUE => "0", --string
                    ECC_MODE => "no_ecc", --string; "no_ecc" or "en_ecc";
                    WAKEUP_TIME => 0 --positive integer; 0 or 2;
                )
                port map (
                    sleep => '0',
                    rst => toHostFifo_rst_wr_clk,
                    wr_clk => toHostFifo_wr_clk,
                    wr_en => toHostFifo_wr_en_pipe,
                    din => toHostFifo_din_pipe,
                    full => open,
                    prog_full => open,
                    wr_data_count => open,
                    overflow => open,
                    wr_rst_busy => open,
                    almost_full => open,
                    wr_ack => open,
                    rd_clk => toHostFifo_rd_clk,
                    rd_en => toHostFifoDistr_rd_en,
                    dout => toHostFifoDistr_dout,
                    empty => toHostFifoDistr_empty,
                    prog_empty => open,
                    rd_data_count => open,
                    underflow => open,
                    rd_rst_busy => open,
                    almost_empty => open,
                    data_valid => open,
                    injectsbiterr => '0',
                    injectdbiterr => '0',
                    sbiterr => open,
                    dbiterr => open
                );

            toHostFifoUram_wr_en <= toHostFifoDistr_dvalid;
            toHostFifoUram_din <= toHostFifoDistr_dout;
            toHostFifoDistr_rd_en <= not toHostFifoDistr_empty and not toHostFifoUram_full;

            process(toHostFifo_rd_clk)
            begin
                if rising_edge(toHostFifo_rd_clk) then
                    toHostFifoDistr_dvalid <= toHostFifoDistr_rd_en;
                end if;
            end process;


            toHostFifoUram0 : xpm_fifo_sync
                generic map (  -- @suppress "Generic map uses default values. Missing optional actuals: CASCADE_HEIGHT, SIM_ASSERT_CHK"
                    FIFO_MEMORY_TYPE => "ultra", --string; "auto", "block", or "distributed";
                    FIFO_WRITE_DEPTH => TOHOSTFIFO_DEPTH(NUMBER_OF_DESCRIPTORS,FIRMWARE_MODE), --positive integer
                    WRITE_DATA_WIDTH => DATA_WIDTH, --positive integer
                    READ_MODE => "fwft", --string; "std" or "fwft";
                    FIFO_READ_LATENCY => 1, --positive integer
                    FULL_RESET_VALUE => 1, --positive integer; 0 or 1;
                    USE_ADV_FEATURES => "0404", -- String
                    READ_DATA_WIDTH => DATA_WIDTH, --positive integer
                    WR_DATA_COUNT_WIDTH => f_log2(TOHOSTFIFO_DEPTH(NUMBER_OF_DESCRIPTORS,FIRMWARE_MODE))+1, --positive integer
                    PROG_FULL_THRESH => TOHOSTFIFO_DEPTH(NUMBER_OF_DESCRIPTORS,FIRMWARE_MODE)-10, --positive integer
                    RD_DATA_COUNT_WIDTH => f_log2(TOHOSTFIFO_DEPTH(NUMBER_OF_DESCRIPTORS,FIRMWARE_MODE))+1, --positive integer
                    PROG_EMPTY_THRESH => 10, --positive integer
                    DOUT_RESET_VALUE => "0", --string
                    ECC_MODE => "no_ecc", --string; "no_ecc" or "en_ecc";
                    WAKEUP_TIME => 2 --positive integer; 0 or 2;
                )
                port map (
                    sleep => '0',
                    rst => toHostFifo_rst_250,
                    wr_clk => toHostFifo_rd_clk,
                    wr_en => toHostFifoUram_wr_en,
                    din => toHostFifoUram_din,
                    full => toHostFifoUram_full,
                    prog_full => open,
                    wr_data_count => toHostFifo_wr_data_count_s_rd_clk,
                    overflow => open,
                    wr_rst_busy => wr_rst_busy,
                    almost_full => open,
                    wr_ack => open,
                    rd_en => toHostFifo_re_array(i),
                    dout => toHostFifo_dout_array(i)(DATA_WIDTH-1 downto 0),
                    empty => open,
                    prog_empty => open,
                    rd_data_count => toHostFifo_rd_data_count_s,
                    underflow => open,
                    rd_rst_busy => open,
                    almost_empty => open,
                    data_valid => open,
                    injectsbiterr => '0',
                    injectdbiterr => '0',
                    sbiterr => open,
                    dbiterr => open
                );
        end generate;


        xpm_cdc_single_wr_rst_busy : xpm_cdc_single
            generic map (
                DEST_SYNC_FF => 2,
                INIT_SYNC_FF => 0,
                SIM_ASSERT_CHK => 0,
                SRC_INPUT_REG => 0
            )
            port map (
                src_clk => '0',
                src_in => wr_rst_busy,
                dest_clk => toHostFifo_wr_clk,
                dest_out => wr_rst_busy_wr_clk
            );

        tohost_prog_full_proc: process(toHostFifo_wr_clk)
        begin
            if rising_edge(toHostFifo_wr_clk) then
                if toHostFifo_wr_data_count_s(f_log2(TOHOSTFIFO_DEPTH(NUMBER_OF_DESCRIPTORS,FIRMWARE_MODE))-1 downto 0) >= toHostFifo_pfull_threshold_assert_s(f_log2(TOHOSTFIFO_DEPTH(NUMBER_OF_DESCRIPTORS,FIRMWARE_MODE))-1 downto 0) then
                    toHostFifo_prog_full_s <= '1';
                elsif toHostFifo_wr_data_count_s(f_log2(TOHOSTFIFO_DEPTH(NUMBER_OF_DESCRIPTORS,FIRMWARE_MODE))-1 downto 0) <= toHostFifo_pfull_threshold_negate_s(f_log2(TOHOSTFIFO_DEPTH(NUMBER_OF_DESCRIPTORS,FIRMWARE_MODE))-1 downto 0) then
                    toHostFifo_prog_full_s <= wr_rst_busy_wr_clk;
                end if;
            end if;
        end process;




        toHostFifo_prog_full(i) <= toHostFifo_prog_full_s;

        tohost_prog_empty_proc: process(toHostFifo_rd_data_count_s, toHostFifo_empty_thresh)
        begin
            --if rising_edge(toHostFifo_rd_clk) then
            if toHostFifo_rd_data_count_s(f_log2(TOHOSTFIFO_DEPTH(NUMBER_OF_DESCRIPTORS,FIRMWARE_MODE))-1 downto 0) <= toHostFifo_empty_thresh(i)(f_log2(TOHOSTFIFO_DEPTH(NUMBER_OF_DESCRIPTORS,FIRMWARE_MODE))-1 downto 0) then
                toHostFifo_prog_empty_s <= '1';
            else
                toHostFifo_prog_empty_s <= '0';
            end if;
        --end if;
        end process;

        toHostFifo_prog_empty(i) <= toHostFifo_prog_empty_s;

        --toHostFifo_wr_data_count_array_s(i)(12 downto f_log2(TOHOSTFIFO_DEPTH)) <= (others => '0');
        --toHostFifo_wr_data_count_array_s(i)(f_log2(TOHOSTFIFO_DEPTH)-1 downto 0) <= toHostFifo_wr_data_count_s(f_log2(TOHOSTFIFO_DEPTH)-1 downto 0);


        pipe0: process (toHostFifo_wr_clk) is
        begin
            if rising_edge(toHostFifo_wr_clk) then
                toHostFifo_din_pipe <= toHostFifo_din(i)(DATA_WIDTH-1 downto 0);
                toHostFifo_wr_en_pipe <= toHostFifo_wr_en(i);
            end if;
        end process pipe0 ;
    end generate g_tohost;


end architecture rtl ; -- of WupperFifos

